package cn.itcast.web.utils;

import cn.itcast.domain.system.SysLog;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.SysLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.UUID;

/**
 * @author LT
 * @version 1.0.0
 * @ClassName LogAspect.java
 * @Description TODO 切面 = 通知+ 切入点表达式
 * @createTime 2020年03月26日 20:49:00
 * <p>
 * AOP ，Aspect Oritentd Programing 面向切面编程
 */
@Aspect // 表示该类是一个切面类
@Component
public class LogAspect {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpSession session;

    @Autowired
    private SysLogService sysLogService;

    //切入点表达式： 返回值类型  包名.类名.方法名(形参类型)
  /*  @Pointcut("execution(* itcast.web.controller.*.*.*(..))")
    public void pt(){}     */
    @Around("execution(* itcast.web.controller.*.*.*(..)) && !execution(* cn.itcast.web.controller.system.SysLogController.*(..))")
    public Object saveLog(ProceedingJoinPoint pj){  // 如果是环绕通知，那么形参必须有一个ProceedingJoinPoint参数，ProceedingJoinPoint代表当前的目标方法
        //1.先让目标方法执行
        Object result = null;
        try {
            result = pj.proceed();
            //2. 创建SysLog对象
            SysLog sysLog  = new SysLog();
            //3. 设置参数给SysLog对象
            sysLog.setId(UUID.randomUUID().toString());
            //获取当前的登陆者
            User loginUser = (User) session.getAttribute("loginUser");
            //设置用户名
            sysLog.setUserName(loginUser.getUserName());
            //设置登陆的ip
            String ip = request.getRemoteAddr();
            sysLog.setIp(ip);
            //设置时间
            sysLog.setTime(new Date());
            //设置当前执行的目标方法名
            //getSignature()获取目标方法的签名
            String methodName = pj.getSignature().getName();
            sysLog.setMethod(methodName);

            //设置方法所属的类名
            String className = pj.getTarget().getClass().getName();
            sysLog.setAction(className);

            sysLog.setCompanyId(loginUser.getCompanyId());
            sysLog.setCompanyName(loginUser.getCompanyName());

            //4. 保存到数据库中
            sysLogService.save(sysLog);

        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return result;
    }

}
